package com.bfl.sa.common.mybatis;

import com.bfl.sa.common.repository.support.annotation.EnableQueryCache;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.core.annotation.AnnotationUtils;

import javax.persistence.Table;
import java.util.List;

public class MapperHelper {

    private static SqlSessionTemplate sessionTemplate;

    private Class<?> entityClass;
    private boolean enableQueryCache = false;
    private String statement;

    public MapperHelper(Class<?> entityClass) {
        this.entityClass = entityClass;
        this.statement = entityClass.getName();

        EnableQueryCache enableQueryCacheAnnotation = AnnotationUtils.findAnnotation(entityClass, EnableQueryCache.class);
        boolean enableQueryCache = false;
        if (enableQueryCacheAnnotation != null) {
            enableQueryCache = enableQueryCacheAnnotation.value();
        }
        this.enableQueryCache = enableQueryCache;
    }

    public static void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
        sessionTemplate = sqlSessionTemplate;
    }

    public String getTableName(Class<?> entityClass) {
        Table table = entityClass.getAnnotation(Table.class);
        if (table != null) {
            return table.name();
        } else {
            return entityClass.getSimpleName();
        }
    }

    public String getStatement(String sqlId) {
        return this.statement + "." + sqlId;
    }

    public static void flush() {
        sessionTemplate.clearCache();
    }

    public static void clear() {
        flush();
        sessionTemplate.clearCache();
    }

    /**
     * 保存对象
     */
    public Object save(Object obj) {
        return sessionTemplate.insert(getStatement("save"), obj);
    }

    /**
     * 批量更新
     */
    public Object batchSave(List list) {
        return sessionTemplate.insert(getStatement("batchSave"), list);
    }

    /**
     * 修改对象
     */
    public Object update(Object obj) {
        return sessionTemplate.update(getStatement("update"), obj);
    }

    /**
     * 批量更新
     */
    public void batchUpdate(List list) {
        SqlSessionFactory sqlSessionFactory = sessionTemplate.getSqlSessionFactory();
        //批量执行器
        try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false)) {
            if (list != null) {
                for (Object aList : list) {
                    sqlSession.update(getStatement("batchUpdate"), aList);
                }
                sqlSession.flushStatements();
                sqlSession.commit();
                sqlSession.clearCache();
            }
        }
    }

    /**
     * 批量更新
     */
    public void batchUpdate(Object... params) {
        SqlSessionFactory sqlSessionFactory = sessionTemplate.getSqlSessionFactory();
        //批量执行器
        try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false)) {
            if (params != null) {
                for (Object param : params) {
                    sqlSession.update(getStatement("batchUpdate"), param);
                }
                sqlSession.flushStatements();
                sqlSession.commit();
                sqlSession.clearCache();
            }
        }
    }

    /**
     * 批量更新
     */
    public Object batchDelete(List list) {
        return sessionTemplate.delete(getStatement("batchDelete"), list);
    }

    /**
     * 删除对象
     */
    public Object delete(Object obj) {
        return sessionTemplate.delete(getStatement("delete"), obj);
    }

    /**
     * 查找对象
     */
    public Object findForObject(Object obj) {
        return sessionTemplate.selectOne(getStatement("findForObject"), obj);
    }

    /**
     * 查找对象
     */
    public Object findForList(Object obj) {
        return sessionTemplate.selectList(getStatement("findForList"), obj);
    }

    public Object findForMap(Object obj, String key, String value) {
        return sessionTemplate.selectMap(getStatement("findForMap"), obj, key);
    }

    public <E> E findOne(Object... params) {
        List<E> list = findAll(params);

        if (list.size() > 0) {
            return list.get(0);
        }
        return null;
    }

    public <E> List<E> findAll(Object... params) {
        return sessionTemplate.selectList(getStatement("findAll"), params);
    }
}
